import os
from App import app, db, app_logger
from App.models import Item, User, SettingModel, AudioModel
from App.forms import RegisterForm, LoginForm, PurchaseItemForm, SellItemForm, SettingForm
from flask import render_template, redirect, url_for, flash, request, jsonify, send_from_directory
from flask_login import login_user, logout_user, login_required, current_user

from App.MyLib.mCnLunar import cnlunar_day, cnlunar_days
from App.MyLib.azureTTS import Mtts
from App.MyLib.douBao import Doubao

import zipfile
from io import BytesIO

# 在全局作用域创建 DB_Setting 和 mTTS 实例
with app.app_context():

    SoundArr = []
    mTTS = None
    DB_Setting = None
    try:
        # 尝试创建数据库表

        DB_Setting = SettingModel.query.first()

        # 尝试获取设置数据
        mTTS= Mtts(DB_Setting, app.audio_dir)

    except:
        # 如果创建表失败，打印错误信息
        db.create_all()
        DB_Setting = SettingModel.query.first()
        if DB_Setting :

            print("创建数据库表成功")
        else:
            print("创建数据库表失败")


@app.route('/get_sounds', methods=['POST'])
def get_sounds():
    mp3_dir = app.audio_dir  # 替换为实际的 mp3 目录路径
    sound_files = [f for f in os.listdir(mp3_dir) if f.endswith('.mp3')]

    # 用于跟踪已处理的文件名称（不包括扩展名）
    processed_basenames = {}
    deleted_files = []

    # 首先收集所有文件和它们的数据库记录
    file_records = {}
    for filename in sound_files:
        speech_model = AudioModel.query.filter_by(filename=filename).first()
        if speech_model:
            # 获取文件名（不含扩展名）
            basename = os.path.splitext(filename)[0]

            # 如果已经处理过这个基本文件名
            if basename in processed_basenames:
                # 比较时间戳，决定保留哪个
                existing_record = processed_basenames[basename]

                # 如果当前记录比已存在的记录更新，则替换并删除旧记录
                if speech_model.updated_at > existing_record.updated_at:
                    old_filename = existing_record.filename
                    file_path = os.path.join(mp3_dir, old_filename)
                    if os.path.exists(file_path):
                        os.remove(file_path)
                        deleted_files.append(old_filename)
                        print(f"删除重复文件 (旧版本): {old_filename}")

                    # 替换为新记录
                    processed_basenames[basename] = speech_model
                    file_records[filename] = speech_model
                    # 从file_records中删除旧记录
                    if old_filename in file_records:
                        del file_records[old_filename]
                else:
                    # 当前记录更旧，删除它
                    file_path = os.path.join(mp3_dir, filename)
                    if os.path.exists(file_path):
                        os.remove(file_path)
                        deleted_files.append(filename)
                        print(f"删除重复文件 (旧版本): {filename}")
            else:
                # 第一次遇到这个基本文件名
                processed_basenames[basename] = speech_model
                file_records[filename] = speech_model
        else:
            # 如果找不到对应的数据，删除该文件
            file_path = os.path.join(mp3_dir, filename)
            if os.path.exists(file_path):
                os.remove(file_path)
                deleted_files.append(filename)
                print(f"删除未记录文件: {filename}")

    # 现在构建返回的对象列表
    sound_objects = []
    for filename, speech_model in file_records.items():
        sound_objects.append({
            'id': speech_model.id,
            'filename': speech_model.filename,
            'azure_voice_name': speech_model.azure_voice_name,
            'path': speech_model.path,
            'video_scripts': speech_model.video_scripts,
            'updated_at': speech_model.updated_at.strftime('%Y-%m-%d %H:%M:%S')
        })

    if deleted_files:
        print(f"已删除以下重复或未记录的文件: {deleted_files}")

    print(f"返回音频列表，共 {len(sound_objects)} 个文件")
    return jsonify(sound_objects)


@app.route('/delete_mp3', methods=['POST'])
def delete_mp3():
    file_names = request.form.getlist('file_names')
    # 修改目录为 static/mp3
    static_folder = os.path.join(app.static_folder, 'mp3')
    for file_name in file_names:
        file_path = os.path.join(static_folder, file_name)
        if os.path.exists(file_path):
            os.remove(file_path)
    return jsonify({"status": "success"})


@app.route('/download_mp3', methods=['POST'])
def download_mp3():
    file_names = request.form.getlist('file_names')
    # 修改目录为 static/mp3
    static_folder = os.path.join(app.static_folder, 'mp3')
    memory_file = BytesIO()
    with zipfile.ZipFile(memory_file, 'w') as zf:
        for file_name in file_names:
            file_path = os.path.join(static_folder, file_name)
            if os.path.exists(file_path):
                zf.write(file_path, file_name)
    memory_file.seek(0)
    return send_from_directory(directory=os.path.dirname(memory_file.name),
                               path=os.path.basename(memory_file.name),
                               as_attachment=True,
                               download_name='selected_mp3s.zip')





# 注册用户
@app.route("/register", methods=['GET', 'POST'])
def RegisterPage():
    form = RegisterForm()
    if form.validate_on_submit():
        create_user = User(username=form.username.data, email_address=form.email_address.data,
                           password=form.password1.data)
        db.session.add(create_user)
        db.session.commit()
        login_user(create_user)
        flash(f'帐户创建成功！您现在以以下身份登录: {create_user.username}', category='success')
        return redirect(url_for('index'))

    if form.errors != {}:
        for error in form.errors.values():
            flash(f'创建用户时出错: {error}', category='danger')
    return render_template('register.html', title='Register', form=form)


@app.route("/login", methods=['GET', 'POST'])
def LoginPage():
    form = LoginForm()
    if form.validate_on_submit():
        attempted_user = User.query.filter_by(username=form.username.data).first()
        if attempted_user and attempted_user.password_check(password_attempt=form.password.data):
            login_user(attempted_user)
            flash(f'成功！您以以下身份登录: {attempted_user.username}', category='success')
            if attempted_user.username == 'admin':
                return redirect(url_for('AdminPage'))
            # 在其他路由函数中，检查所有重定向到登录页面的代码
            return redirect(url_for('tts_index'))  # 确保使用 'LoginPage' 而不是 'login'
        flash('用户名和密码不匹配！请重试', category='danger')
    return render_template('login.html', title='Login', form=form)



@app.route("/logout")
def LogoutPage():
    logout_user()
    flash("您已注销！", category='info')
    return redirect(url_for('index'))


# 初始化数据库 112
@app.route('/getlunars', methods=['POST'])
def getdays():
    data = request.get_json()
    cnlunar_str = None
    # 传入的是 日期字符串数组
    cnlunar_prompt = data['num']
    print(f"cnlunar_prompt     {cnlunar_prompt}")

    # str_key  传入的是 日期字符串数组  返回的是  日期字符串数组 对应的 阴历信息  字典
    cnlunar_str = cnlunar_days(cnlunar_prompt)
    print(cnlunar_str)
    return jsonify(cnlunar_str)


@app.route('/videscript', methods=['POST'])
def get_script():
    try:
        print(f"get_script :   .... \n  ")
        data = request.get_json()
        doubaoVS = Doubao(DB_Setting.db_base_url, DB_Setting.db_api_key, DB_Setting.init_prompt)
        strCnlunar = data["prompt"]
        video_scripts = doubaoVS.generate_text(strCnlunar)
        print(f"video_scripts :  {video_scripts} \n  ")
        # 其他处理逻辑
        return jsonify({"index": data["index"], "video_scripts": video_scripts}), 200
    except Exception as e:
        return jsonify({"error": f"生成视频脚本出错  \n {e}"}), 400


@app.route('/run', methods=['POST'])
def run_tts():
    try:
        print("run_tts  ")
        mRequest = request.get_json()
        print("创建数据对象 完成", mRequest)

        for mKey in mRequest:
            if 'prompt_' in mKey:
                print(f"找到  : {mKey}")
                prompt = mRequest[mKey]
                file_speech = mTTS.run(prompt)
                print("file_speech111", file_speech)

                mAudioModel = AudioModel(filename=file_speech["filename"],
                                         azure_voice_name=file_speech["azure_voice_name"],
                                         path=file_speech["path"], video_scripts=file_speech["video_scripts"])

                db.session.add(mAudioModel)
                db.session.commit()  # 提交到数据库

        return jsonify({
            'message': 'ok',
            'mp3': file_speech
        }), 200
    except Exception as e:
        print(f"生成音频出错  \n {e}")
        return jsonify({"error": f"生成音频出错  \n {e}"}), 400


@app.route("/setting", methods=['GET', 'POST'])
@login_required  # 添加登录验证
def setting():
    try:
        form = SettingForm()
        if form.validate_on_submit():
            if DB_Setting:
                print("DB_Setting.db_base_url  ", DB_Setting.db_base_url)
                DB_Setting.db_base_url = form.db_base_url.data
                DB_Setting.db_api_key = form.db_api_key.data
                DB_Setting.azure_ttsapi_key = form.azure_ttsapi_key.data
                DB_Setting.azure_region = form.azure_region.data
                DB_Setting.init_prompt = form.init_prompt.data
                # print(f"form.init_prompt.data   {form.init_prompt.data}")
                DB_Setting.start_prompt = form.start_prompt.data
                form.video_scripts.data = DB_Setting.video_scripts

                db.session.commit()
                flash(f'提交API相关设置: 成功  ', category='success')
    except Exception as e:
        print(f"Setting 路由  错误  获取数据库失败: {e}")

    form.init_prompt.data = DB_Setting.init_prompt
    return render_template('setting.html', form=form, DB_Setting=DB_Setting)


@app.route('/tts', methods=['GET'])
@login_required  # 添加登录验证
def tts_index():
    with app.app_context():
        db.create_all()
        print("所有数据表已创建。")
    try:
        form = SettingForm()
    except Exception as e:
        print(f"Setting 路由  错误  获取数据库失败: {e}")
    if form.validate_on_submit():
        if DB_Setting:
            DB_Setting.azure_voice_name = form.azure_voice_name.data  # 语音类型
            DB_Setting.init_prompt = form.init_prompt.data  # 初始化提示语
            db.session.commit()
            flash(f'提交: 成功  ', category='success')
        else:
            flash(f'找不到 :Setting 数据 或者其他有关数据库错误  ', category='success')

    print("打开主页")
    form.init_prompt.data = DB_Setting.init_prompt
    return render_template('tts.html', form=form, DB_Setting=DB_Setting)


@app.route('/', methods=['GET'])
def index():
    print("打开主页")
    app_logger.info("用户进入主页")
    return render_template('index.html' )

@app.route('/install', methods=['GET'])
def install():
    with app.app_context():
        db.create_all()
        print("所有数据表已创建。")
    return "创建数据表"


## 另一种解决方案

# 如果您更喜欢保持使用 `url_for('login')`，您可以将路由函数名改为 `login`：